﻿using HalconDotNet;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ZRFCore.Camera;
using ZRFCore.MachineVisionAlgorithm.ShapeMatching;
using ZRFCore.Tool;
using ZRFCore.MachineVisionAlgorithm.Controls.ZrfWindowControl.Model;
using ZRFCore.MachineVisionAlgorithm.Calibration2D;
using ZRFCore.MachineVisionAlgorithm.Controls.ZrfWindowControl.Path;

namespace MultiAxisVisionAssembly.VisionAlgorithm
{
    public class Vision
    {
        public ICamera Camera;//相机
        private string camParPath = Directory.GetCurrentDirectory() + "\\homMat2d\\calib";//内参路径
        private string posPath = Directory.GetCurrentDirectory() + "\\homMat2d\\calib";//外参路径
        private string worldPlaneToMachCoordHomMat2dPath = Directory.GetCurrentDirectory() + "\\homMat2d\\calib";//世界坐标转机械坐标矩阵

        private uint DefaultDelayToOutGlue = 0;//单位：ms
        private uint DefaultOutGlueToStartMove = 0;//单位：ms
        private uint DefaultPointOutGlueToStartMove = 500;//单位：ms
        private uint DefaultStopGlueDelayTime = 0;//单位：ms
        private float DefaultWorkHeight = 30;//单位：mm
        private double DefaultSpeed = 15;//单位：mm/s

        private string fileNameExt = String.Empty;
        private string filePath = String.Empty;

        private ICalibration2D calibration;
        private Proj proj;

        private double xldPathGroup1DeviationDistY = 0;
        private double xldPathGroup1DeviationDistX = 0;
        private double xldPathGroup1Width = 20;//图像窗口表示的路径宽度

        private double xldPathGroup2DeviationDistY = 10;
        private double xldPathGroup2DeviationDistX = 10;
        private double xldPathGroup2Width = 5;

        /// <summary>
        /// 模板匹配对象
        /// </summary>
        public ShapeMatching ShapeMatching { get { return proj.ShapeMatching; } }

        /// <summary>
        /// 创建找图模板的区域
        /// </summary>
        public List<IPathPart> ModelRegions { get { return proj.ShapeModelRegions; } set { proj.ShapeModelRegions = value; } }

        /// <summary>
        /// 找全图得到的模板
        /// </summary>
        public FoundModel[] FoundModels { get { return ShapeMatching.FoundModels; } }

        public Vision()
        {
            proj = new Proj();
            try
            {
                Camera = CameraIdBoundHelper.CreateCamera<Camera_HKVision>();
            }
            catch (Exception)
            {
                throw new Exception("打开相机失败！");
            }

            try
            {
                calibration = new NinePointCalibByCamParamPos(camParPath, posPath, worldPlaneToMachCoordHomMat2dPath);
            }
            catch
            {
                throw new Exception("标定文件加载失败！");
            }
        }

        /// <summary>
        /// 保存工程
        /// </summary>
        public void SaveProj()
        {
            try
            {
                FileHelper.SaveFileDialog<Proj>(proj, "点胶方案(*.glue)|*.glue", out fileNameExt, out filePath);
            }
            catch (Exception e)
            {
                fileNameExt = String.Empty;
                filePath = String.Empty;
                Log.ShowErrorDialog(e.Message);
            }
        }

        public void LoadProj()
        {
            try
            {
                Proj proj = FileHelper.LoadFileDialog<Proj>("点胶方案(*.glue)|*.glue", out fileNameExt, out filePath);
                if (proj == null)
                {
                    Log.ShowErrorDialog("请打开可用文件");
                }
                else
                {
                    this.proj = proj;
                }
            }
            catch (Exception e)
            {
                proj = new Proj();
                fileNameExt = String.Empty;
                filePath = String.Empty;
                Log.ShowErrorDialog(e.Message);
            }
        }
    }

    /// <summary>
    /// 窗口上xldPath的附加信息
    /// </summary>
    [Serializable]
    public class XldPathInfo
    {
        /// <summary>
        /// 路径名称
        /// </summary>
        public string Name = String.Empty;
        /// <summary>
        /// 到起始点延时出胶的时间
        /// </summary>
        public uint Delay_DelayToOutGlue { get; set; }
        /// <summary>
        /// 起始点持续出胶时间
        /// </summary>
        public uint Delay_OutGlueToStartMove { get; set; }
        /// <summary>
        /// 出胶结束延时的时间
        /// </summary>
        public uint Delay_StopGlueDelayTime { get; set; }
        /// <summary>
        /// 点胶速度
        /// </summary>
        public double Speed { get; set; }
        /// <summary>
        /// 屏蔽标志
        /// </summary>
        public bool Shield { get; set; }
    }

    /// <summary>
    /// 机械坐标图像路径
    /// </summary>
    public class MachCoord2dPath : XldPathInfo
    {
        /// <summary>
        /// 机械坐标2D路径
        /// </summary>
        /// <param name="imageXldPathInfo"></param>
        /// <param name="xldPath"></param>
        /// <param name="calibration2D"></param>
        /// <param name="zWorkPos">Z轴运行的高度</param>
        /// <param name="snapPosX"></param>
        /// <param name="snapPosY"></param>
        public MachCoord2dPath(XldPathInfo xldPathInfo, XldPath xldPath, ICalibration2D calibration2D, float zWorkPos, double snapPosX, double snapPosY, double machCoordDeviationX = 0, double machCoordDeviationY = 0)
        {
            //子类赋值
            var parentProperties = xldPathInfo.GetType().GetProperties();
            foreach (var parentProperty in parentProperties)
            {
                var thisProperty = this.GetType().GetProperty(parentProperty.Name, parentProperty.PropertyType);
                var value = parentProperty.GetValue(xldPathInfo);
                if (thisProperty != null && value != null && thisProperty.CanWrite)
                {
                    thisProperty.SetValue(this, value);
                }
            }
            calibration2D.ImgXldToMachCoordPoints(xldPath.XLD, out double[] Xs, out double[] Ys);
            double offsetX = snapPosX - calibration2D.SnapImgMachX + machCoordDeviationX;
            double offsetY = snapPosY - calibration2D.SnapImgMachY + machCoordDeviationY;
            xPoses = Xs.Select(v => v + offsetX).ToArray();
            yPoses = Ys.Select(v => v + offsetY).ToArray();
            zPoses = new double[yPoses.Length];
            Array.Fill(zPoses, zWorkPos);
        }
        public double[] XPoses { get { return xPoses; } }
        public double[] YPoses { get { return yPoses; } }
        public double[] ZPoses { get { return zPoses; } }
        private double[] xPoses;
        private double[] yPoses;
        private double[] zPoses;
    }

    /// <summary>
    /// 工程
    /// </summary>
    [Serializable]
    public class Proj
    {
        public Proj()
        {

        }
        public float XSnapPos { get; set; }
        public float YSnapPos { get; set; }
        public float ZSnapPos { get; set; }
        /// <summary>
        /// 工程图片
        /// </summary>
        public HImage? WholeImg { get { return wholeImg?.Clone(); } set { wholeImg = value; } }
        private HImage? wholeImg;
        /// <summary>
        /// 路径信息
        /// </summary>
        public List<XldPathInfo> XldPathInfos = new List<XldPathInfo>();
        /// <summary>
        /// 路径
        /// </summary>
        public List<XldPath> XldPaths = new List<XldPath>();
        /// <summary>
        /// 模板匹配
        /// </summary>
        public ShapeMatching ShapeMatching = new ShapeMatching();
        /// <summary>
        /// 模板匹配的区域，1为需要区域，2为忽略区域
        /// </summary>
        public List<IPathPart> ShapeModelRegions = new List<IPathPart>();
    }
}
